const jwt = require('jsonwebtoken')
const config = require('../config')
const tool = require('./tool')
const ApiError = require('../error/api_error');
const ApiErrorNames = require('../error/api_error_name');
const ApiErrorMap = require('../error/api_error_map');

const self = {}
//生成token
self.createToken = exports.createToken = (user) => {
  //console.log("传入的USER",user)
  //expiresIn：以秒表示或描述时间跨度zeit / ms的字符串。如60，"2 days"，"10h"，"7d"，Expiration time，过期时间
  const token = jwt.sign({userId: user.userId, userName: user.userName,rank:user.rank}, config.tokenSecret, {expiresIn: 60*20});
  return token;
};

// 解密token返回userId,userName用来判断用户身份。
self.decodeToken = exports.decodeToken = (ctx) => {
  const token = tool.getTokenFromCtx(ctx);
  const userObj = jwt.decode(token, config.tokenSecret);
  return userObj;
};

// 检查token 要指定哪些要检查哪些不要查检两个数组URL
// exports.checkToken1 = (apiPrefix, shouldCheckPathArray, unlessCheckPathArray) => async (ctx, next) => {
//   //如果是api前缀的检查token
//   if (ctx.request.path.startsWith(apiPrefix)) {
//     const currentUrl = ctx.request.url;
//     const {method} = ctx.request;
//
//     const unlessCheck = unlessCheckPathArray.some((url) => currentUrl.indexOf(url) > -1);
//
//     const shouldCheck = shouldCheckPathArray.some((url) => currentUrl.indexOf(url) > -1) && method !== 'GET';
//     //再查看是不是在需要检查的路由列表里
//     if (shouldCheck && !unlessCheck) {
//       const token = tool.getTokenFromCtx(ctx);
//       if (token) {
//         try {
//           jwt.verify(token, config.tokenSecret);
//           await next();
//         } catch (error) {
//           ctx.status = 401;
//           ctx.body = {msg: 'token无效', detal: error};
//         }
//       } else {
//         ctx.status = 401;
//         ctx.body = '无 token，请登录';
//       }
//     } else {
//       await next();
//     }
//   } else {
//     //不是apiapi前缀的不检查token
//     await next();
//   }
// };

/**
 * 检查token 指定哪些不要检查 其余都要检查
 * @param apiPrefix
 * @param unlessCheckPathArray 指定不需要检查的url
 * @param shouldCheckPathArray  需要检查但是放get方法不检查
 * @returns {Function}
 */

exports.checkToken = (apiPrefix, unlessCheckPathArray, shouldCheckPathArray) => async (ctx, next) => {
  //如果是api前缀的检查token
  if (ctx.request.path.startsWith(apiPrefix)) {
    const currentUrl = ctx.request.url;
    const {method} = ctx.request;

    const unlessCheck = unlessCheckPathArray.some((url) => currentUrl.indexOf(url) > -1);
    const shouldPass = shouldCheckPathArray.some((url) => currentUrl.indexOf(url) > -1) && method == 'GET';

    if (shouldPass) {
      await next();
     // return
    }else if (!unlessCheck) {  //不在放行列表需要检查的路由列表里
      await docheck(ctx, next)
    } else {//在放行列表
      await next();
    }
    //   const token = tool.getTokenFromCtx(ctx);
    //
    //   if (token) {
    //     try {
    //       await jwt.verify(token, config.tokenSecret);
    //       await next();
    //       if (!ctx.body) {
    //         //是api开头但是后面的url是错的,给respinse_formaater去');
    //         ctx.status = 404;
    //         throw new ApiError(ApiErrorNames.NOT_FOUND);
    //       }//是api开头但是后面的url是错的，返回值为空报404
    //     } catch (error) {
    //       //"有错误发生")
    //       //如果是模型内部返回的错误直接抛出
    //       if (error instanceof ApiError) {
    //         throw error;
    //       }
    //       //不是的话
    //       ctx.status = 401;
    //       throw new ApiError(ApiErrorNames.TOKEN_ERROR);
    //     }
    //   } else {
    //     ctx.status = 401;
    //     ctx.body = '无 token，请登录';
    //   }
    // } else {//在放行列表
    //   await next();
    // }
  } else {
    //不是api前缀的不检查token
    await next();
  }

  async function docheck(ctx, next) {
    const token = tool.getTokenFromCtx(ctx);
    if (token) {
      //验证token
      try {
        await jwt.verify(token, config.tokenSecret);
      } catch (error) {
        // //如果是模型内部返回的错误直接抛出
        // if (error instanceof ApiError) {
        //   throw error;
        // }
        //不是的话
        ctx.status = 401;
        if (error.message === "jwt expired") {
          throw new ApiError(ApiErrorNames.TOKEN_EXPIRED);
        }
        throw new ApiError(ApiErrorNames.TOKEN_ERROR);
      }
      //验证通过后放行
      await next();
      //检查返回数据
      if (!ctx.body) {
        //是api开头但是后面的url是错的;
        ctx.status = 404;
        throw new ApiError(ApiErrorNames.NOT_FOUND);
      }//是api开头但是后面的url是错的，返回值为空报404
      if (ctx.status === 200 && ctx.url !== "/api/refreshToken") {
        //验证完了有正解返回值，在响应头放入新的token
        let user = self.decodeToken(ctx);
        let newToken = self.createToken(user);
        ctx.set('token', newToken)
      }
    } else {//没有token
      ctx.status = 401;
      throw new ApiError(ApiErrorNames.NO_TOKEN);
      // ctx.body = {code: 'no_auth', msg: '无 token，请登录'};
    }
  }
};
//检查api路由下的token
// exports.checkApiToken = (apiPrefix) => async (ctx, next) => {
//   var token = ctx.headers.authorization;
//   if (token == undefined) {
//     await next();
//   } else {
//
//   }
// }
